package com.molichuxing.services.business.service.impl;

import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.services.business.convertor.Convert;
import com.molichuxing.services.business.dto.request.modify.OrderModifyBizDto;
import com.molichuxing.services.business.dto.request.modify.OrderReturnCarModifyBizDto;
import com.molichuxing.services.business.dto.request.modify.OrderReturnDisputeDisposalsModifyBizDto;
import com.molichuxing.services.business.dto.request.modify.OrderReturnPdiModifyBizDto;
import com.molichuxing.services.business.service.OrderReturnBizService;
import com.molichuxing.services.business.service.OrderSubscribeBizService;
import com.molichuxing.services.infrastructure.dto.request.create.OrderSubscribeSettlementCreateDto;
import com.molichuxing.services.infrastructure.dto.request.modify.OrderReturnCarModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.OrderSubscribeSettlementModifyDto;
import com.molichuxing.services.infrastructure.dto.response.OrderSubscribeDto;
import com.molichuxing.services.infrastructure.dto.response.OrderSubscribeSettlementDto;
import com.molichuxing.services.infrastructure.service.OrderReturnService;
import com.molichuxing.services.infrastructure.service.OrderStatusFlowService;
import com.molichuxing.services.infrastructure.service.OrderSubscribeService;
import com.molichuxing.services.infrastructure.service.OrderSubscribeSettlementService;
import com.molichuxing.services.property.OrderStatusFlowModifiedTypeEnum;
import com.molichuxing.services.property.OrderSubscribeStatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;

/**
 * 订单退车biz service
 *
 * @author zoumingyu
 * @date 2019年10月28日
 */
@Service("orderReturnBizService")
public class OrderReturnBizServiceImpl implements OrderReturnBizService {
    private static final Logger logger = LoggerFactory.getLogger(OrderReturnBizServiceImpl.class);

    @Resource
    private OrderReturnService orderReturnService;

    @Resource
    private OrderSubscribeService orderSubscribeService;

    @Resource
    private OrderSubscribeSettlementService orderSubscribeSettlementService;

    @Resource
    private OrderStatusFlowService orderStatusFlowService;

    @Resource
    private OrderSubscribeBizService orderSubscribeBizService;

    /**
     * 订单还车修改订单-订阅订单
     *
     * @param modifyBizDto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyReturnCar(OrderReturnCarModifyBizDto modifyBizDto) {
        Boolean result = false;
        // 查询订阅订单信息
        OrderSubscribeDto orderSubscribeDto = orderSubscribeService.getOrderSubscribe(modifyBizDto.getOrderCode());
        if (orderSubscribeDto == null) {
            logger.error("[modifyReturnCar]订阅订单({})不存在", modifyBizDto.getOrderCode());
            return result;
        } else if (!OrderSubscribeStatusEnum.TRADE_USE.equals(orderSubscribeDto.getOrderStatus())) {
            logger.error("[modifyReturnCar]订阅订单({})状态({})不是用车中({})", modifyBizDto.getOrderCode(),
                    orderSubscribeDto.getOrderStatus(), OrderSubscribeStatusEnum.TRADE_USE);
            return result;
        } else if (orderSubscribeDto.getIsHaveSuborder()) {
            logger.error("[modifyReturnCar]订单({})存在续订单", modifyBizDto.getOrderCode());
            return result;
        }
        orderSubscribeDto.setSettleMileage(modifyBizDto.getCurrentMileage());
        if (orderSubscribeDto.getEndMileage() == null || orderSubscribeDto.getEndMileage() == 0) {
            orderSubscribeDto.setEndMileage(modifyBizDto.getCurrentMileage());
        }
        // 修改订单信息
        OrderReturnCarModifyDto modifyDto = new OrderReturnCarModifyDto();
        modifyDto.setOrderCode(orderSubscribeDto.getOrderCode());
        modifyDto.setEndMileage(orderSubscribeDto.getEndMileage());
        modifyDto.setSettleMileage(orderSubscribeDto.getSettleMileage());
        result = orderSubscribeService.modifyReturnCar(modifyDto);
        if (!result) {
            return result;
        }
        // 新增流转信息
        orderStatusFlowService.createOrderStatusFlow(Convert.toOrderStatusFlowCreateDto(modifyBizDto));
        // 新增还车信息
        orderReturnService.create(Convert.toOrderReturnCreateDto(modifyBizDto, orderSubscribeDto));

        // 计算超里程数
        Integer beyondMileage = calculateBeyondMileage(orderSubscribeDto, 0, 0);
        // 计算超期数(当前日期-截止日)
        long differDay = DateUtil.getDaysDiff(orderSubscribeDto.getLeaseExpire(), LocalDate.now());
        Integer beyondDay = differDay > 0L ? (int) differDay : 0;
        // 新增结算信息
        orderSubscribeSettlementService.create(Convert
                .toOrderSubscribeSettlementCreateDto(modifyBizDto, beyondMileage, beyondDay));

        return result;
    }

    /**
     * 还车计算超里程数
     *
     * @param orderSubscribeDto
     * @param beyondMileage
     * @param num
     * @return
     */
    private Integer calculateBeyondMileage(OrderSubscribeDto orderSubscribeDto, Integer beyondMileage, Integer num) {
        num = num == null ? 0 : num;
        beyondMileage = beyondMileage == null ? 0 : beyondMileage;
        if (num > 100) {
            logger.error("[calculateBeyondMileage]还车计算超里程数异常，递归次数({})异常", num);
            throw new BizException("还车计算超里程数异常");
        }
        // 判断结算里程是否大于订单到期里程
        if (orderSubscribeDto.getSettleMileage() > orderSubscribeDto.getEndMileage()) {
            beyondMileage += orderSubscribeDto.getSettleMileage() > orderSubscribeDto.getWarningMileage()
                    ? orderSubscribeDto.getSettleMileage() - orderSubscribeDto.getWarningMileage() : 0;
        } else {
            beyondMileage += orderSubscribeDto.getEndMileage() > orderSubscribeDto.getWarningMileage()
                    ? orderSubscribeDto.getEndMileage() - orderSubscribeDto.getWarningMileage() : 0;
        }
        // 是否存在父订单
        if (orderSubscribeDto.getParentOrderCode() != null && orderSubscribeDto.getParentOrderCode() > 0L) {
            // 存在，查询父订单信息
            OrderSubscribeDto parentOrderSubscribeDto = orderSubscribeService
                    .getOrderSubscribe(orderSubscribeDto.getParentOrderCode());
            if (parentOrderSubscribeDto == null) {
                logger.error("[calculateBeyondMileage]还车计算超里程数异常，父订单({})不存在", orderSubscribeDto.getParentOrderCode());
                throw new BizException("还车计算超里程数异常");
            }
            // 递归计算超里程数
            beyondMileage = calculateBeyondMileage(parentOrderSubscribeDto, beyondMileage, num);
        }

        return beyondMileage;
    }

    /**
     * 订单还车pdi检测完成修改订单
     *
     * @param modifyBizDto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyReturnPdi(OrderReturnPdiModifyBizDto modifyBizDto) throws BizException {
        // 查询订单信息
        OrderSubscribeDto orderSubscribeDto = orderSubscribeService.getOrderSubscribe(modifyBizDto.getOrderCode());
        if (orderSubscribeDto == null) {
            logger.error("[modifyReturnPdi]订阅订单({})不存在", modifyBizDto.getOrderCode());
            return false;
        } else if (!OrderSubscribeStatusEnum.RETURN_UNINSPECTED.equals(orderSubscribeDto.getOrderStatus())) {
            logger.error("[modifyReturnPdi]订阅订单({})状态({})不是待验车({})", modifyBizDto.getOrderCode(),
                    orderSubscribeDto.getOrderStatus(), OrderSubscribeStatusEnum.RETURN_UNINSPECTED);
            return false;
        }
        // 质损费
        BigDecimal damageFee = modifyBizDto.getDamageFee() == null ? BigDecimal.ZERO : modifyBizDto.getDamageFee();
        // 查询结算信息
        OrderSubscribeSettlementDto orderSubscribeSettlementDto = orderSubscribeSettlementService
                .getOrderSubscribeSettlement(orderSubscribeDto.getOrderCode());
        if (orderSubscribeSettlementDto == null) {
            // 无结算信息，新增
            OrderSubscribeSettlementCreateDto settlementCreateDto = Convert
                    .toOrderSubscribeSettlementCreateDto(modifyBizDto.getOrderCode(), damageFee);
            if (!orderSubscribeSettlementService.create(settlementCreateDto)) {
                logger.error("[modifyReturnPdi]订阅订单({})新增结算信息失败", modifyBizDto.getOrderCode());
                return false;
            }
        } else {
            // 存在，修改
            OrderSubscribeSettlementModifyDto settlementModifyDto = Convert
                    .toOrderSubscribeSettlementModifyDto(orderSubscribeSettlementDto, damageFee);
            if (!orderSubscribeSettlementService.modifyPdi(settlementModifyDto)) {
                logger.error("[modifyReturnPdi]订阅订单({})修改结算信息失败", modifyBizDto.getOrderCode());
                return false;
            }
        }

        // 修改订阅订单状态、新增流转状态
        OrderModifyBizDto orderModifyBizDto = new OrderModifyBizDto();
        orderModifyBizDto.setOrderCode(modifyBizDto.getOrderCode());
        orderModifyBizDto.setOperateId(modifyBizDto.getCheckId());
        orderModifyBizDto.setOperateName(modifyBizDto.getCheckName());
        orderModifyBizDto.setOrderStatus(OrderSubscribeStatusEnum.RETURN_UNCONFIRM);
        orderModifyBizDto.setPreOrderStatus(OrderSubscribeStatusEnum.RETURN_UNINSPECTED);
        orderModifyBizDto.setModifiedType(OrderStatusFlowModifiedTypeEnum.B_USER);
        if (!orderSubscribeBizService.modifySubscribeStatus(orderModifyBizDto)) {
            logger.error("[modifyReturnPdi]订单还车pdi检测完成修改订阅订单({})失败", modifyBizDto.getOrderCode());
            throw new BizException("订单还车pdi检测完成修改订阅订单失败");
        }
        return true;
    }

    /**
     * 订单还车验车报告确认
     *
     * @param modifyBizDto
     * @return
     * @throws BizException
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public Boolean modifyReportConfirm(OrderModifyBizDto modifyBizDto) throws BizException {
        // 查询订单信息
        OrderSubscribeDto orderSubscribeDto = orderSubscribeService.getOrderSubscribe(modifyBizDto.getOrderCode());
        if (orderSubscribeDto == null) {
            logger.error("[modifyReportConfirm]订阅订单({})不存在", modifyBizDto.getOrderCode());
            return false;
        } else if (!OrderSubscribeStatusEnum.RETURN_UNCONFIRM.equals(orderSubscribeDto.getOrderStatus())) {
            logger.error("[modifyReportConfirm]订阅订单({})状态({})不是待用户确认({})", modifyBizDto.getOrderCode(),
                    orderSubscribeDto.getOrderStatus(), OrderSubscribeStatusEnum.RETURN_UNCONFIRM);
            return false;
        }
        // 修改订单
        Boolean result = orderSubscribeBizService.modifySubscribeStatus(modifyBizDto);
        if (result) {
            // 判断状态
            OrderSubscribeStatusEnum status = (OrderSubscribeStatusEnum) modifyBizDto.getOrderStatus();
            if (!OrderSubscribeStatusEnum.RETURN_FINISH.equals(status)) {
                return true;
            }
            // 已完成状态，修改结算信息
            try {
                if (!orderSubscribeSettlementService.modifySettlement(modifyBizDto.getOrderCode())) {
                    logger.error("[modifyReportConfirm]订阅订单({})修改无费用结算失败", modifyBizDto.getOrderCode());
                    return false;
                }
            } catch (Exception e) {
                logger.error("[modifyReportConfirm]订阅订单({})修改无费用结算异常", modifyBizDto.getOrderCode());
                return false;
            }
        }

        return true;
    }

    /**
     * 订单还车争议处理完成修改订单
     *
     * @param modifyDto
     * @return
     * @throws BizException
     */
    @Override
    public Boolean modifyReturnDisputeDisposals(OrderReturnDisputeDisposalsModifyBizDto modifyBizDto)
            throws BizException {
        // 查询订单信息
        OrderSubscribeDto orderSubscribeDto = orderSubscribeService.getOrderSubscribe(modifyBizDto.getOrderCode());
        if (orderSubscribeDto == null) {
            logger.error("[modifyReturnDisputeDisposals]订阅订单({})不存在", modifyBizDto.getOrderCode());
            return false;
        } else if (!OrderSubscribeStatusEnum.RETURN_INTERVENE.equals(orderSubscribeDto.getOrderStatus())) {
            logger.error("[modifyReturnDisputeDisposals]订阅订单({})状态({})不是协商({})", modifyBizDto.getOrderCode(),
                    orderSubscribeDto.getOrderStatus(), OrderSubscribeStatusEnum.RETURN_INTERVENE);
            return false;
        }

        OrderSubscribeStatusEnum status = OrderSubscribeStatusEnum.RETURN_UNPAID;
        // 查询结算信息
        OrderSubscribeSettlementDto orderSubscribeSettlementDto = orderSubscribeSettlementService
                .getOrderSubscribeSettlement(orderSubscribeDto.getOrderCode());
        if (orderSubscribeSettlementDto == null) {
            logger.error("[modifyReturnDisputeDisposals]订阅订单({})结算信息不存在", modifyBizDto.getOrderCode());
            return false;
        }
        // 判断金额
        BigDecimal damageFee = modifyBizDto.getDamageFee() == null ? BigDecimal.ZERO : modifyBizDto.getDamageFee();
        if (damageFee.compareTo(orderSubscribeSettlementDto.getDamageFee()) != 0) {
            // 质损费有变动，修改结算信息
            OrderSubscribeSettlementModifyDto settlementModifyDto = Convert
                    .toOrderSubscribeSettlementModifyDto(orderSubscribeSettlementDto, damageFee);
            if (!orderSubscribeSettlementService.modifyDisputeDisposals(settlementModifyDto)) {
                logger.error("[modifyReturnDisputeDisposals]订阅订单({})修改结算信息失败", modifyBizDto.getOrderCode());
                return false;
            }

            status = settlementModifyDto.getTotalFee().compareTo(BigDecimal.ZERO) > 0
                    ? OrderSubscribeStatusEnum.RETURN_UNPAID : OrderSubscribeStatusEnum.RETURN_FINISH;
        }
        // 修改订阅订单状态、新增流转状态
        OrderModifyBizDto orderModifyBizDto = new OrderModifyBizDto();
        orderModifyBizDto.setOrderCode(modifyBizDto.getOrderCode());
        orderModifyBizDto.setOperateId(modifyBizDto.getDisposalsId());
        orderModifyBizDto.setOperateName(modifyBizDto.getDisposalsName());
        orderModifyBizDto.setOrderStatus(status);
        orderModifyBizDto.setPreOrderStatus(OrderSubscribeStatusEnum.RETURN_INTERVENE);
        orderModifyBizDto.setModifiedType(OrderStatusFlowModifiedTypeEnum.B_USER);
        if (!orderSubscribeBizService.modifySubscribeStatus(orderModifyBizDto)) {
            logger.error("[modifyReturnDisputeDisposals]订单还车争议处理完成修改订阅订单({})失败", modifyBizDto.getOrderCode());
            throw new BizException("订单还车争议处理完成修改订阅订单失败");
        }
        return true;
    }
}
